// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="CustomDependencyResolver.cs" company="Scrum for Team System">
//   None
// </copyright>
// <summary>
//   Defines the CustomDependencyResolver type.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------

namespace ScrumForTeamSystem.EventService.Services
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;

    using ScrumForTeamSystem.EventService.Infrastructure;
    using ScrumForTeamSystem.EventService.Infrastructure.Interfaces;
    using ScrumForTeamSystem.EventService.Services.Properties;

    /// <summary>
    /// Defines the CustomDependencyResolver type.
    /// </summary>
    internal class CustomDependencyResolver : IDependencyResolver
    {
        /// <summary>
        /// Hash table of services
        /// </summary>
        private readonly Dictionary<Type, object> services;

        /// <summary>
        /// <c>true</c> is first time run; otherwise false
        /// </summary>
        private bool isFirstRun;

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomDependencyResolver"/> class.
        /// </summary>
        public CustomDependencyResolver()
        {
            this.services = new Dictionary<Type, object>();
            this.isFirstRun = true;
        }

        /// <summary>
        /// Gets the implementation of the specified type.
        /// </summary>
        /// <typeparam name="T">The type to return</typeparam>
        /// <returns>Instance of type specified</returns>
        /// <exception cref="Exception">
        /// </exception>
        public T GetImplementationOf<T>()
        {
            if (this.isFirstRun)
            {
                this.isFirstRun = false;
                this.SetUp();
            }

            if (!this.services.ContainsKey(typeof(T)))
            {
                throw new ServiceException("CustomDependencyResolver", string.Format(CultureInfo.InvariantCulture, Resources.String006, typeof(T).Name));
            }

            return (T)this.services[typeof(T)];
        }

        /// <summary>
        /// Sets up the service.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Action log service does not implement IDisposable, so cannot be disposed.")]
        public void SetUp()
        {
            IActionLoggingService actionLogService = new ActionLogService();
            ICachingService cachingService = new CachingService();
            IEventQueueService eventQueueService = new EventQueueService();
            IWorkerProcess workerProcess = new WorkerProcess(eventQueueService);
            IServerConnectionService serverConnectionService = new ServerConnectionService();
            IWorkItemStoreRepository workItemStoreRepository = new WorkItemStoreRepository(
                    serverConnectionService, cachingService);

            this.services.Add(typeof(ICachingService), cachingService);
            this.services.Add(typeof(IEventQueueService), eventQueueService);
            this.services.Add(typeof(IWorkerProcess), workerProcess);
            this.services.Add(typeof(IServerConnectionService), serverConnectionService);
            this.services.Add(typeof(IWorkItemStoreRepository), workItemStoreRepository);
            this.services.Add(typeof(IActionLoggingService), actionLogService);

            actionLogService.RegisterLogGenerator(eventQueueService);
            actionLogService.RegisterLogGenerator(workerProcess);
            actionLogService.RegisterLogGenerator(serverConnectionService);
            actionLogService.RegisterLogGenerator(workItemStoreRepository);
            actionLogService.RegisterLogGenerator(cachingService);

            try
            {
                var init = new EventProcessorsLoader(workerProcess, actionLogService);
                init.LoadPluginAssemblies();
            }
            catch (ServiceException serviceException)
            {
                actionLogService.LogEventMessage(Resources.String007);
                actionLogService.WriteToEventLog(serviceException);
            }

            actionLogService.LogEventMessage(Resources.String008);
            actionLogService.WriteToEventLog(Resources.String008);
        }
    }
}